package com.freemalll.merchant.utils;

import com.freemalll.common.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author luohui
 */
@Slf4j
@Component
public class RedisUtil {

    @Autowired
    protected RedissonClient redissonClient;

    @Autowired
    private RedisService redisService;



    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisService.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存获取
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisService.getCacheObject(key);
    }
    /**
     * 普通缓存放入
     * @param key 键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key, Object value) {
        try {
            redisService.setCacheObject(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @param key 键
     * @return true成功 false失败
     */
    public boolean remove(String key) {
        try {
            redisService.deleteObject(key);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 批量删除
     * @param pattern
     */
    public void removeAll(final String... pattern) {
        for (String kp : pattern) {
            redisService.deleteObject(redisService.keys(kp + "*"));
        }
    }

    /**
     * 带过期时间的 单位默认秒
     * @param key 键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key,Object value,long timeout) {
        try {
            redisService.setCacheObject(key, value, timeout,TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 带过期时间和单位的
     * @param key 键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key,Object value,long timeout,TimeUnit timeUnit) {
        try {
            redisService.setCacheObject(key, value, timeout,timeUnit);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 获取分布式锁
     *
     * @param key
     * @param value
     * @param expireInSeconds 锁超时时间 秒
     * @return
     */
    public Boolean getLock(String key,String value,Long expireInSeconds) throws InterruptedException {
        RLock lock = redissonClient.getLock(key+":"+value);
        return lock.tryLock(expireInSeconds,TimeUnit.SECONDS);
    }

    /**
     * 获取分布式锁
     *
     * @param key
     * @param waitTime 等待获取锁超时时间
     * @param leaseTime 获取锁的超时时间 强制释放
     * @return
     */
    public Boolean tryLock(String key,long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
        RLock lock = redissonClient.getLock(key);
        return lock.tryLock(waitTime,leaseTime,unit);
    }

    /**
     * 启用看门狗机制
     * @param key
     * @param waitTime
     * @param unit
     * @return
     * @throws InterruptedException
     */
    public Boolean tryLock(String key, long waitTime, TimeUnit unit) throws InterruptedException {
        RLock lock = redissonClient.getLock(key);
        return lock.tryLock(waitTime, unit);
    }

    /**
     * 判断当前线程是否持有该锁
     * @param key
     * @return
     */
    public boolean isLocked(String key) {
        RLock lock = redissonClient.getLock(key);
        return lock.isHeldByCurrentThread();
    }

    /**
     * 分布式锁unlock，使用lua脚本保证事务
     * @param key
     */
    public void unlock(String key){
        RLock lock = redissonClient.getLock(key);
        lock.unlock();
    }
}
